package com.daervin.svc.manager;

import com.daervin.svc.common.constants.SourceEnum;
import com.daervin.svc.common.constants.StockOpTypeEnum;
import com.daervin.svc.common.dto.PageResultDTO;
import com.daervin.svc.common.dto.SearchStockRecordDTO;
import com.daervin.svc.common.dto.WhStockRecordDTO;
import com.daervin.svc.common.exception.CommonException;
import com.daervin.svc.common.exception.ErrorCode;
import com.daervin.svc.common.utils.DateTimeUtils;
import com.daervin.svc.dal.WhProductMapper;
import com.daervin.svc.dal.WhStockMapper;
import com.daervin.svc.dal.WhStockRecordMapper;
import com.daervin.svc.dal.model.WhProductDO;
import com.daervin.svc.dal.model.WhStockDO;
import com.daervin.svc.dal.model.WhStockRecordDO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by daervin on 2023/8/18
 */
@Component
public class StockManager {
    @Resource
    private WhStockMapper stockMapper;
    @Resource
    private WhStockRecordMapper stockRecordMapper;
    @Resource
    private WhProductMapper whProductMapper;

    public Integer getStockByProductId(Long productId) {
        if (productId == null || productId <= 0) {
            return 0;
        }
        WhStockDO stockDO = stockMapper.selectByProductId(productId);
        return stockDO == null || stockDO.getStock() == null ? 0 : stockDO.getStock();
    }

    public boolean initStockByProductId(Long productId) {
        if (productId == null || productId <= 0) {
            throw new CommonException(ErrorCode.ERROR_PARAM, "商品未初始化");
        }
        WhStockDO stockDO = stockMapper.selectByProductId(productId);
        if (stockDO != null) {
            return true;
        }
        WhStockDO record = new WhStockDO();
        record.setProductId(productId);
        record.setStock(0);
        record.setCreateTime(new Date());
        record.setUpdateTime(record.getCreateTime());
        stockMapper.insertSelective(record);
        return record.getId() > 0;
    }

    public boolean updateStockByProductId(Long productId, Integer stock, StockOpTypeEnum opTypeEnum, SourceEnum sourceEnum) {
        WhStockDO stockDO = stockMapper.selectByProductId(productId);
        if (stockDO == null) {
            throw new CommonException(ErrorCode.ERROR_PARAM, "库存未初始化");
        }

        int num = stock;
        if (StockOpTypeEnum.OUT.equals(opTypeEnum)) {
            if (stockDO.getStock() - stock < 0) {
                throw new CommonException(ErrorCode.ERROR_PARAM, String.format("库存不足,当前【%s】,待操作【%s】", stockDO.getStock(), stock));
            }
            num = -stock;
        }

        addStockRecord(stockDO.getId(), stock, opTypeEnum, sourceEnum);

        WhStockDO record = new WhStockDO();
        record.setId(stockDO.getId());
        record.setStock(num);
        int count = stockMapper.updateByPrimaryKeySelective(record);
        return count > 0;
    }

    public void addStockRecord(Long skuId, Integer stock, StockOpTypeEnum opTypeEnum, SourceEnum sourceEnum) {
        WhStockRecordDO record = new WhStockRecordDO();
        record.setSkuId(skuId);
        record.setStock(stock);
        record.setOpType(opTypeEnum.val);
        record.setOpUser(sourceEnum.desc);
        record.setCreateTime(new Date());
        record.setUpdateTime(record.getCreateTime());
        stockRecordMapper.insertSelective(record);
    }

    public PageResultDTO<WhStockRecordDTO> getRecordByPage(SearchStockRecordDTO req) {
        PageResultDTO<WhStockRecordDTO> result = new PageResultDTO<>();
        result.setCurrPage(req.getPageNo());
        result.setPageCount(0);
        int totalCount = 0;
        WhProductDO productDO = whProductMapper.selectByPrimaryKey(req.getProductId());
        if (productDO != null) {
            WhStockDO stockDO = stockMapper.selectByProductId(productDO.getId());
            if (stockDO != null) {
                req.setSkuId(stockDO.getId());
            }
            totalCount = stockRecordMapper.selectCount(req);
        }
        result.setTotalCount(totalCount);
        if (totalCount == 0) {
            return result;
        }
        result.setPageCount(totalCount % req.getPageSize() == 0 ? totalCount / req.getPageSize() : totalCount / req.getPageSize() + 1);
        int offset = (req.getPageNo() - 1) * req.getPageSize();
        req.setOffset(offset);
        List<WhStockRecordDO> list = stockRecordMapper.selectList(req);

        List<WhStockRecordDTO> recordDTOList = new ArrayList<>();
        list.stream().forEach(it -> {
            WhStockRecordDTO recordDTO = new WhStockRecordDTO();
            BeanUtils.copyProperties(it, recordDTO);
            recordDTO.setOpTypeStr(StockOpTypeEnum.valOf(it.getOpType()).getDesc());
            recordDTO.setCreateTimeStr(DateTimeUtils.longParse(it.getCreateTime()));
            recordDTO.setUpdateTimeStr(DateTimeUtils.longParse(it.getUpdateTime()));
            recordDTOList.add(recordDTO);
        });
        result.setResults(recordDTOList);
        return result;
    }

    public boolean removeRecord(Long recordId) {
        WhStockRecordDO recordDO = stockRecordMapper.selectByPrimaryKey(recordId);
        if (recordDO == null || recordDO.getOpType().equals(StockOpTypeEnum.DEL.val)) {
            return true;
        }
        WhStockDO stockDO = stockMapper.selectById(recordDO.getSkuId());
        if (stockDO == null) {
            throw new CommonException(ErrorCode.ERROR_PARAM, "找不到商品！！！");
        }
        StockOpTypeEnum opTypeEnum = StockOpTypeEnum.valOf(recordDO.getOpType());
        if (StockOpTypeEnum.IN.equals(opTypeEnum) && stockDO.getStock() < recordDO.getStock()) {
            throw new CommonException(ErrorCode.ERROR_PARAM, "当前剩余库存不足以撤销此进货记录！！！");
        }
        stockRecordMapper.deleteByPrimaryKey(recordId);
        WhStockDO record = new WhStockDO();
        record.setId(stockDO.getId());
        record.setStock(StockOpTypeEnum.IN.equals(opTypeEnum) ? -recordDO.getStock() : recordDO.getStock());
        stockMapper.updateByPrimaryKeySelective(record);
        return true;
    }
}
